/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	bar_scan.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-05-24
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "foreach_plunger.h"



/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

#define DEVICE_UART_TX_SIZE	64
#define DEVICE_UART_RX_SIZE	64
#define FOREACH_BAUDRATE 38400

#define N0_MAX_STEP		3143
#define N1_MAX_STEP		50288
#define N2_MAX_STEP		1002617

/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/
static void uart_recv_callback(void* arg,uint8_t *rxbuff,uint16_t rxsize);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
/*
send reset: 2F 31 4E 31 5A 52 0D
receive:2F 30 40 03 0D 0A 

send qury:2F 31 51 0D
receive:2F 30 60 03 0D 0A 

send qury tip:2F 31 3F 33 31 0D
receive:2F 30 60 31 03 0D 0A 

send read capacity:2F 31 3F 36 38 0D
receive:2F 30 60 35 03 0D 0A 

send pos:2F 31 41 35 30 30 30 30 52 0D
receive:2F 30 40 03 0D 0A 
*/
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/
static char rtn_head[] = {0x2F,0x30};
static char rtn_tail[] = {0x03,0x0D,0x0A};
static bus_t m_bus;
static bsp_uart_t* p_bsp_uart = NULL;
static char bsp_tx_buff[DEVICE_UART_TX_SIZE];
static char bsp_rx_buff[DEVICE_UART_RX_SIZE];
static plunger_t* p_device_head = NULL;
static pfn_plunger_status_callback plunger_cb = NULL;
/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/
uint8_t bsp_plunger_init(pfn_plunger_status_callback pfn)
{
	plunger_cb = pfn;
	p_bsp_uart = bsp_uart_init(PLUNGER_UART_CHN,FOREACH_BAUDRATE);
	bsp_uart_tx_dma_init(p_bsp_uart,NULL);
	bsp_uart_rx_dma_init(p_bsp_uart,uart_recv_callback,bsp_rx_buff,DEVICE_UART_RX_SIZE);
}
plunger_t* plunger_init(uint8_t ascii_address)
{
	plunger_t* p_new = malloc(sizeof(plunger_t));
	if(p_new == NULL)
	{
		Trace_Log("malloc err;\n");
		return NULL;
	}
	memset(p_new,0,sizeof(plunger_t));
	p_new->address = ascii_address;
	if(p_device_head == NULL)
	{
		p_device_head = p_new;
//		return p_new;
	}
	else
	{
		plunger_t* p_tail = p_device_head;
		while(p_tail->next != NULL)
		{
			p_tail = p_tail->next;
		}
		p_tail->next = p_new;
	}
	plungnger_home(p_new);
	return p_new;
}
uint8_t plunger_capacity(plunger_t* p_device,uint32_t capacity)
{
	if(p_device != NULL)
	{
		p_device->capacity_threshold = capacity;
	}
	return p_device->p_status;
}
uint8_t plunger_pos(plunger_t* p_device,int32_t pos)
{
	if(p_device == NULL)
		return 0;
	bsp_uart_wait_tx_dma_cplt(p_bsp_uart);
	char* data = bsp_tx_buff;
	*data++ = '/';
	*data++ = p_device->address;
	*data++ = CMD_POS;
	data = data + sprintf(data,"%d",pos);
//	*data++ = pos%;
	*data++ = CMD_EXCUTE;
	*data++ = '\r';
	bsp_uart_dma_transfer(p_bsp_uart,bsp_tx_buff,data - bsp_tx_buff);
	m_bus.last_address =  p_device->address;
	m_bus.last_cmd = CMD_POS;
	m_bus.wait_ack = 1;
	m_bus.bus_interval = 0;
	p_device->p_status = PSTATUS_MOVING;
//	if(capacity != 0)
//	{
//		p_device->capacity_threshold = capacity;
//	}
	return p_device->p_status;
}
uint8_t plungnger_home(plunger_t* p_device)
{
	if(p_device == NULL)
		return 0;
	bsp_uart_wait_tx_dma_cplt(p_bsp_uart);
	char* data = bsp_tx_buff;
	*data++ = '/';
	*data++ = p_device->address;
	*data++ = CMD_RESOLUTION;
	*data++ = '1';
	*data++ = CMD_INIT;
	*data++ = CMD_EXCUTE;
	*data++ = '\r';
	bsp_uart_dma_transfer(p_bsp_uart,bsp_tx_buff,data - bsp_tx_buff);
	m_bus.last_address =  p_device->address;
	m_bus.last_cmd = CMD_INIT;
	m_bus.wait_ack = 1;
	m_bus.bus_interval = 0;
	p_device->p_status = PSTATUS_HOMING;
	return p_device->p_status;
}
uint8_t plungnger_qury_status(plunger_t* p_device)
{
	if(p_device == NULL)
		return 0;
	bsp_uart_wait_tx_dma_cplt(p_bsp_uart);
	char* data = bsp_tx_buff;
	*data++ = '/';
	*data++ = p_device->address;
	*data++ = CMD_READ_STATUS;
	data = data + sprintf(data,"%d",TIP_STATUS);
//	*data++ = CMD_QURY_BUFF;
//	*data++ = CMD_EXCUTE;
	*data++ = '\r';
	bsp_uart_dma_transfer(p_bsp_uart,bsp_tx_buff,data - bsp_tx_buff);
	m_bus.last_address =  p_device->address;
	m_bus.last_cmd = CMD_READ_STATUS;
	m_bus.wait_ack = 1;
	m_bus.last_qury_address = TIP_STATUS;
	return p_device->p_status;
}
uint8_t plungnger_qury_capacity(plunger_t* p_device)
{
	if(p_device == NULL)
		return 0;
	bsp_uart_wait_tx_dma_cplt(p_bsp_uart);
	char* data = bsp_tx_buff;
	*data++ = '/';
	*data++ = p_device->address;
	*data++ = CMD_READ_STATUS;
	data = data + sprintf(data,"%d",CAPACITANCE);
//	*data++ = CMD_EXCUTE;
	*data++ = '\r';
	bsp_uart_dma_transfer(p_bsp_uart,bsp_tx_buff,data - bsp_tx_buff);
	m_bus.last_address =  p_device->address;
	m_bus.last_cmd = CMD_READ_STATUS;
	m_bus.wait_ack = 1;
	m_bus.last_qury_address = CAPACITANCE;
	return p_device->p_status;
}
plunger_status_t plunger_get_status(plunger_t* p_device)
{
	return p_device->p_status;
}
static void uart_recv_callback(void* arg,uint8_t *rxbuff,uint16_t rxsize)
{
	if(memcmp(rtn_head,rxbuff,sizeof(rtn_head)) != 0
		|| m_bus.wait_ack != 1
		)
	{
		Trace_Log("foreach illegal rx head %02X %02X;\n",rxbuff[0],rxbuff[1]);
		return;
	}
	plunger_t* p_device = p_device_head;
	while(p_device != NULL && p_device->address != m_bus.last_address)
	{
		p_device = p_device->next;
	}
	if(p_device == NULL)
	{
		Trace_Log("can't find device;\n");
		return;
	}
	uint8_t status = 0;
	status = *(rxbuff + sizeof(rtn_head));
	p_device->qstatus = status;
	if((status & QSTATUS_ERR) != 0)
	{
		if(plunger_cb != NULL)
		{
			plunger_cb(p_device,PLUNGER_CATCH_ERR);
		}
		p_device->p_status = PSTATUS_ERR;
		Trace_Log("foreach err code %X;\n",status);
	}
	else if((QSTATUS_IDLE & status) == QSTATUS_IDLE)
	{
		if((p_device->p_status == PSTATUS_MOVING || p_device->p_status == PSTATUS_HOMING) && plunger_cb != NULL)
		{
			plunger_cb(p_device,PLUNGER_MOVE_CPLT);
		}
		p_device->p_status = PSTATUS_IDLE;
	}
	else
	{
//		p_device->p_status = PSTATUS_BUSY;
	}
	switch(m_bus.last_cmd)
	{
		case CMD_QURY_BUFF:
		case CMD_INIT:
		case CMD_POS:
			break;
		case CMD_READ_STATUS:
		{
			if(m_bus.last_qury_address == TIP_STATUS)
			{
				p_device->tipstatus = *(rxbuff + sizeof(rtn_head) + 1);
				/*tip 回调TBD*/
			}
			else if(m_bus.last_qury_address == CAPACITANCE)
			{
				p_device->capacitance = 0;
				for(uint16_t index = sizeof(rtn_head) + 1;index < rxsize;index++)
				{
					if((*(rxbuff + index) >= '0') && (*(rxbuff + index) <= '9'))
					{
						p_device->capacitance = p_device->capacitance*10 + (*(rxbuff + index) - 0x30);
					}
					else
					{
						break;
					}
				}
				if(plunger_cb != NULL && p_device->capacitance >= p_device->capacity_threshold)
				{
					plunger_cb(p_device,PLUNGER_CAPACITY_EXCEED);
					p_device->capacity_threshold = 0;
				}
			}
			break;//2F 30 60 35 03 0D 0A 
		}
		default:break;
	}
	m_bus.last_address = 0;
	m_bus.last_cmd = 0;
	m_bus.wait_ack = 0;
	m_bus.last_qury_address = 0;
}
uint8_t plunger_poll(int64_t tick)
{
	if(m_bus.wait_ack || (tick % FOREACH_POLL_INTERVAL != 0))
		return 0;
	plunger_t* p_device = p_device_head;
	while(p_device != NULL)
	{
		if(p_device->p_status == PSTATUS_MOVING || p_device->p_status == PSTATUS_HOMING)
		{
			if(m_bus.bus_interval == 0)
			{
				m_bus.bus_interval = 1;
//				return p_device->p_status;
			}
			else
				plungnger_qury_status(p_device);
//			return p_device->p_status;
		}
		else if(p_device->capacity_threshold != 0)
		{
			plungnger_qury_capacity(p_device);
//			return p_device->p_status;
		}
		p_device = p_device->next;
	}
	return 0;
}
uint8_t plunger_bus_enable(void)
{
	if(m_bus.wait_ack)
		return 0;
	return 1;
}
